package com.gibs.peixunapi.service.impl;

import com.gibs.peixunapi.VO.BusinessVO;
import com.gibs.peixunapi.VO.OptionVO;
import com.gibs.peixunapi.VO.RoleVO;
import com.gibs.peixunapi.VO.UserVO;
import com.gibs.peixunapi.dao.BusinessDao;
import com.gibs.peixunapi.dao.UserDao;
import com.gibs.peixunapi.enums.ResultEnum;
import com.gibs.peixunapi.excepiton.BaseException;
import com.gibs.peixunapi.model.Business;
import com.gibs.peixunapi.model.User;
import com.gibs.peixunapi.result.PageData;
import com.gibs.peixunapi.result.Result;
import com.gibs.peixunapi.service.BusinessService;
import com.gibs.peixunapi.service.RoleService;
import com.gibs.peixunapi.service.UserAndRoleService;
import com.gibs.peixunapi.service.UserService;
import com.gibs.peixunapi.utils.ConverterUtil;
import com.gibs.peixunapi.utils.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.persistence.EntityNotFoundException;
import javax.persistence.Transient;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private BusinessDao businessDao;
    @Autowired
    private UserAndRoleService userAndRoleService;
    @Autowired
    private RoleService roleService;


    @Override
    //TODO 1.绑定公司 2.绑定角色 3.密码加密
    public Result create(UserVO object) {
        try {
            User user = new User();
            object.setId(null);
            ConverterUtil.copyNotBlankProperties(object, user);
            user.setStatus(1);
            user.setAudit(0);
            userDao.save(user);
            return ResultUtil.success(ResultEnum.CREATE_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(ResultEnum.CREATE_FAIL);
        }
    }


    @Override
    @Modifying(clearAutomatically = true)
    public Result save(UserVO object) {
        try {

            User user = userDao.getOne(object.getId());
            //排除null值数据
            ConverterUtil.copyNotNullProperties(object, user);
            if (object.getBusinessVO() != null && object.getBusinessVO().getId() != null) {
                Business business = businessDao.findById(object.getBusinessVO().getId()).orElseThrow(EntityNotFoundException::new);
                user.setBusiness(business);
            }
            user.setUpdateTime(new Date());
            userDao.save(user);
            return ResultUtil.success(ResultEnum.UPDATE_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            if (e instanceof EntityNotFoundException) {
                throw new EntityNotFoundException();
            } else {
                throw new BaseException(ResultEnum.UPDATE_FAIL);
            }
        }
    }

    @Override
    public Result delete(Integer id) {
        try {
            userDao.deleteById(id);
            return ResultUtil.success(ResultEnum.DELETE_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(ResultEnum.DELETE_FAIL);
        }
    }

    @Override
    public Result deleteBatch(List<Integer> id) {
        try {
            id.forEach(i -> userDao.deleteById(i));

            return ResultUtil.success(ResultEnum.DELETE_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(ResultEnum.DELETE_FAIL);
        }
    }


    @Override
    public Result get(Integer id) {
        User user = userDao.findById(id).orElseThrow(EntityNotFoundException::new);

        UserVO userVO = new UserVO();
        ConverterUtil.copyProperties(user, userVO, "password", "loginTime", "audit", "status");

        BusinessVO businessVO = new BusinessVO();
        ConverterUtil.copyProperties(user.getBusiness(), businessVO);

        List<RoleVO> roleVOList = userAndRoleService.getRoleVOListByUserId(user.getId());
        userVO.setBusinessVO(businessVO);
        userVO.setRoleVOList(roleVOList);

        return ResultUtil.success(ResultEnum.FIND_SUCCESS, userVO);
    }


    @Override
    public Result getList(String type) {
        try {
            String[] types = type.split(",");

            List<User> list = new ArrayList<>();
            if (!StringUtils.isEmpty(type)) {
                list = userDao.findLike("%" + type + "%");
            } else {
                list = userDao.findAll();
            }
            if (list.size() == 0) {
                ResultUtil.successPage(ResultEnum.DATA_NOT_FIND);
            }
            List<Object> data = new ArrayList<>();
            for (User object : list) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("id", object.getId());
                map.put("username", object.getUsername() == null ? "" : object.getUsername());
                map.put("telephone", object.getTelephone() == null ? "" : object.getTelephone());
                map.put("password", object.getPassword() == null ? "" : object.getPassword());
                map.put("wechatName", object.getWechatName() == null ? "" : object.getWechatName());
                map.put("wechatOpenId", object.getWechatOpenId() == null ? "" : object.getWechatOpenId());
                map.put("IP", object.getIP() == null ? "" : object.getIP());
                map.put("loginTime", object.getLoginTime() == null ? "" : object.getLoginTime());
                map.put("status", object.getStatus() == null ? "" : object.getStatus());
//                map.put("Role", object.getRole() == null ? "" : object.getRole());
                map.put("business", object.getBusiness() == null ? "" : object.getBusiness());
                map.put("certificateType", object.getCertificateType() == null ? "" : object.getCertificateType());
                map.put("certificateNumber", object.getCertificateNumber() == null ? "" : object.getCertificateNumber());
                map.put("email", object.getEmail() == null ? "" : object.getEmail());
                HashMap<String, Object> sex = new HashMap<String, Object>();
//                sex.put("name", object.getSex() == null ? "" : object.getSex().getName());
//                sex.put("id", object.getSex() == null ? "" : object.getSex().getId());
                map.put("sex", sex);
                map.put("audit", object.getAudit() == null ? "" : object.getAudit());
                data.add(map);
            }
            return ResultUtil.success(ResultEnum.FIND_SUCCESS, data);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultUtil.error(ResultEnum.FIND_FAIL);
        }
    }


    @Override
    public Result getListPage(String type, Integer status, Integer page, Integer limit) {
        List<UserVO> userVOList = new ArrayList<>();
        limit = limit == null ? 10 : limit;
        page = page == null ? 1 : page;
        int total = 0;

        Page<User> userPage;
        Pageable pageable = PageRequest.of(page - 1, limit);

        if (!StringUtils.isEmpty(type)) {
            userPage = userDao.findByStatus(status, pageable);
        } else {
            List<Integer> roleIdList = roleService.getIdListByCode(type);
            List<Integer> userIdList = userAndRoleService.getUserIdListByRoleIdList(roleIdList);
            userPage = userDao.findByIdInAndStatus(userIdList, status, pageable);
        }

        total = (int) userPage.getTotalElements();
        if (total == 0) {
            throw new BaseException(ResultEnum.DATA_NOT_FIND);
        }

        for (User user : userPage.getContent()) {
            UserVO userVO = new UserVO();
            ConverterUtil.copyProperties(user, userVO, "loginTime", "audit", "status",
                    "certificateType", "certificateType", "audit");
            BusinessVO businessVO = new BusinessVO();
            ConverterUtil.copyProperties(user.getBusiness(), businessVO);
            List<RoleVO> roleVOList = userAndRoleService.getRoleVOListByUserId(user.getId());
            userVO.setBusinessVO(businessVO);
            userVO.setRoleVOList(roleVOList);
            userVOList.add(userVO);
        }

//            List<Object> data = new ArrayList<>();
//            for (User object : list) {
//                HashMap<String, Object> map = new HashMap();
//                map.put("id", object.getId());
//                map.put("username", object.getUsername() == null ? "" : object.getUsername());
//                map.put("telephone", object.getTelephone() == null ? "" : object.getTelephone());
//                map.put("password", object.getPassword() == null ? "" : object.getPassword());
//                map.put("wechatName", object.getWechatName() == null ? "" : object.getWechatName());
//                map.put("wechatOpenId", object.getWechatOpenId() == null ? "" : object.getWechatOpenId());
//                map.put("IP", object.getIP() == null ? "" : object.getIP());
//                map.put("loginTime", object.getLoginTime() == null ? "" : object.getLoginTime());
//                map.put("status", object.getStatus() == null ? "" : object.getStatus());
//                map.put("Role", object.getRole() == null ? "" : object.getRole());
//                map.put("business", object.getBusiness() == null ? "" : object.getBusiness());
//                map.put("certificateType", object.getCertificateType() == null ? "" : object.getCertificateType());
//                map.put("certificateNumber", object.getCertificateNumber() == null ? "" : object.getCertificateNumber());
//                map.put("email", object.getEmail() == null ? "" : object.getEmail());
//                HashMap<String, Object> sex = new HashMap<String, Object>();
//                sex.put("name", object.getSex() == null ? "" : object.getSex().getName());
//                sex.put("id", object.getSex() == null ? "" : object.getSex().getId());
//                map.put("sex", sex);
//                map.put("audit", object.getAudit() == null ? "" : object.getAudit());
//                data.add(map);
//            }
        PageData<List<UserVO>> pageData = new PageData<>((int) userPage.getTotalElements(), limit, page, userVOList);
        return ResultUtil.successPage(ResultEnum.SUCCESS, pageData);

    }


    @Override
    public Result getOptions(String key, Integer page, Integer limit) {
            List<User> userList;
            Page<User> userPage;
            Pageable pageable = PageRequest.of(page - 1, limit);

            if (!StringUtils.isEmpty(key)) {
                userPage = userDao.findUsersByUsernameContaining(key, pageable);
            } else {
                userPage = userDao.findAll(pageable);
            }
            if (userPage.getContent().size() == 0) {
                throw new EntityNotFoundException();
            }

            userList = userPage.getContent();
            List<OptionVO> data = new ArrayList<>();

            int count = 1;
            for (User object : userList) {
                OptionVO optionVO = new OptionVO(object.getId(), count++, object.getUsername());
                data.add(optionVO);
            }

            PageData<List<OptionVO>> pageData = new PageData<>((int) userPage.getTotalElements(), limit, page, data);
            return ResultUtil.successPage(ResultEnum.SUCCESS, pageData);

    }

    @Override
    @Modifying(clearAutomatically = true)
    public Result audit(List<Integer> idList) {
        try {
            userDao.auditBatchUserByIdList(idList, new Date());
            return ResultUtil.success(ResultEnum.UPDATE_SUCCESS);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(ResultEnum.UPDATE_FAIL);
        }
    }

    @Override
    @Modifying(clearAutomatically = true)
    public Result changePassword(Integer id, String password) {
        //TODO 密码加密过程...
        userDao.changePasswordById(id, password, new Date());
        return null;
    }
}

